home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2007 December / PCWKCD1207B.iso / Blogowanie poza sfera / Flock 1.0 beta / flock-1.0RC3.en-US.win32.exe / flock / components / flockXangaService.js < prev    next >
Text File  |  2007-10-18  |  19KB  |  567 lines

  1. // vim: ts=2 sw=2 expandtab cindent
  2. //
  3. // BEGIN FLOCK GPL
  4. // 
  5. // Copyright Flock Inc. 2005-2007
  6. // http://flock.com
  7. // 
  8. // This file may be used under the terms of of the
  9. // GNU General Public License Version 2 or later (the "GPL"),
  10. // http://www.gnu.org/licenses/gpl.html
  11. // 
  12. // Software distributed under the License is distributed on an "AS IS" basis,
  13. // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. // for the specific language governing rights and limitations under the
  15. // License.
  16. // 
  17. // END FLOCK GPL
  18.  
  19. const ENABLE_DEBUG = true; // switch to turn off slow debug code for production
  20. function DEBUG(x) { if (ENABLE_DEBUG) debug("flockXangaService: "+x+"\n"); }
  21.  
  22. const Cc = Components.classes;
  23. const Ci = Components.interfaces;
  24. const Cr = Components.results;
  25.  
  26. const XANGA_CID = Components.ID("{4a67cc66-aafa-4df6-a836-c63bc92651e7}");
  27. const XANGA_CONTRACTID = "@flock.com/people/xanga;1";
  28. const XANGA_FAVICON = "http://www.xanga.com/favicon.ico";
  29. const SERVICE_ENABLED_PREF = "flock.service.xanga.enabled";
  30. const CATEGORY_COMPONENT_NAME = "Xanga JS Component"
  31. const CATEGORY_ENTRY_NAME = "xanga"
  32.  
  33. const RDFS = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
  34.  
  35.  
  36. // ====================================================
  37. // ========== BEGIN General helper functions ==========
  38. // ====================================================
  39.  
  40. var gCompTK;
  41. function getCompTK() {
  42.   if (!gCompTK) {
  43.     gCompTK = Components.classes["@flock.com/singleton;1"]
  44.                         .getService(Components.interfaces.flockISingleton)
  45.                         .getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
  46.                         .wrappedJSObject;
  47.   }
  48.   return gCompTK;
  49. }
  50.  
  51.  
  52. function loadSubScript(spec) {
  53.   var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
  54.   var context = {};
  55.   loader.loadSubScript(spec, context);
  56.   return context;
  57. }
  58.  
  59. var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
  60.         .getService(Ci.mozIJSSubScriptLoader);
  61. loader.loadSubScript("chrome://browser/content/utilityOverlay.js");
  62.  
  63.  
  64. // ================================================
  65. // ========== BEGIN flockXGService class ==========
  66. // ================================================
  67.  
  68. function flockXGService()
  69. {
  70.   var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
  71.   obs.addObserver(this, "xpcom-shutdown", false);
  72.   this.status = Ci.flockIWebService.STATUS_UNKNOWN;
  73.   this.url = "http://www.xanga.com";
  74.   this.mIsInitialized = false;
  75.   this._ctk = {
  76.     interfaces: [
  77.       "nsISupports",
  78.       "nsIClassInfo",
  79.       "nsISupportsCString",
  80.       "nsIObserver",
  81.       "flockIWebService",
  82.       "flockIManageableWebService",
  83.       "flockIBlogWebService"
  84.     ],
  85.     shortName: "xanga",
  86.     fullName: "Xanga",
  87.     description: "Flock Xanga Service",
  88.     favicon: XANGA_FAVICON,
  89.     CID: XANGA_CID,
  90.     contractID: XANGA_CONTRACTID,
  91.     accountClass: flockXGAccount
  92.   };
  93.   this._profiler = Cc["@flock.com/profiler;1"].getService(Ci.flockIProfiler);
  94.   this.init();
  95. }
  96.  
  97.  
  98. // BEGIN nsIObserver
  99. flockXGService.prototype.observe =
  100. function flockXGService_observe(subject, topic, state)
  101. {
  102.   switch (topic) {
  103.     case "xpcom-shutdown":
  104.       var obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
  105.       obs.removeObserver(this, "xpcom-shutdown");
  106.       return;
  107.   }
  108. }
  109. // END nsIObserver
  110.  
  111.  
  112. // BEGIN flockIWebService
  113. flockXGService.prototype.addAccountById =
  114. function flockXGService_addAccountById(aUsername, aIsTransient, aListener)
  115. {
  116.   this.logger.info("addAccountById('"+aUsername+"')");
  117.   var accountURN = this.acUtils.createAccount(this, aUsername);
  118.   var c_account = this.faves_coop.get(accountURN);
  119.   c_account.isTransient = aIsTransient;
  120.   c_account.service = this.xgService;
  121.   this.USER = accountURN;
  122.  
  123.   // add blog
  124.   var c_blog = new this.faves_coop.Blog(accountURN+":uniqueblog", {
  125.     name: aUsername,
  126.     title: aUsername,
  127.     blogid: aUsername,
  128.     apiLink: "",
  129.     URL: "http://www.xanga.com/private/yourhome.aspx?user="+aUsername,
  130.   });
  131.   c_account.children.addOnce(c_blog);
  132.  
  133.   var acct = this.getAccount(accountURN);
  134.   if (aListener) aListener.onSuccess(acct, "addAccount");
  135.   return acct;
  136. }
  137.  
  138.  
  139. flockXGService.prototype.init =
  140. function flockXGService_init()
  141. {
  142.   DEBUG(".init()");
  143.  
  144.   // Prevent re-entry
  145.   if (this.mIsInitialized) return;
  146.   this.mIsInitialized = true;
  147.  
  148.   var evtID = this._profiler.profileEventStart("xanga-init");
  149.  
  150.   this.prefService = Components.classes["@mozilla.org/preferences-service;1"]
  151.                                .getService(Components.interfaces.nsIPrefBranch);
  152.   if ( this.prefService.getPrefType(SERVICE_ENABLED_PREF) &&
  153.        !this.prefService.getBoolPref(SERVICE_ENABLED_PREF) )
  154.   {
  155.     DEBUG("Pref "+SERVICE_ENABLED_PREF+" set to FALSE... not initializing.");
  156.     var catMgr = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
  157.     catMgr.deleteCategoryEntry("wsm-startup", CATEGORY_COMPONENT_NAME, true);
  158.     catMgr.deleteCategoryEntry("flockWebService", CATEGORY_ENTRY_NAME, true);
  159.     return;
  160.   }
  161.  
  162.   // Logger
  163.   this.logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
  164.   this.logger.init("xanga");
  165.  
  166.   // Attributes of flockIBlogWebService
  167.   this.supportsCategories = 0;
  168.   this.supportsPostReplace = false;
  169.   this.metadataOverlay = "chrome://flock/content/blog/xangaOverlay.xul";
  170.  
  171.   this.acUtils = Cc["@flock.com/account-utils;1"].getService(Ci.flockIAccountUtils);
  172.  
  173.   this.faves_coop = Cc["@flock.com/singleton;1"]
  174.                     .getService(Ci.flockISingleton)
  175.                     .getSingleton("chrome://flock/content/common/load-faves-coop.js")
  176.                     .wrappedJSObject;
  177.  
  178.   this.account_root = this.faves_coop.accounts_root;
  179.  
  180.   this.xgService = new this.faves_coop.Service('urn:xanga:service');
  181.   this.xgService.name = 'xanga';
  182.   this.xgService.desc = 'The Xanga.com Service';
  183.   this.xgService.domains = "xanga.com";
  184.   this.xgService.serviceId = XANGA_CONTRACTID;
  185.  
  186.   var xgHomepage = new this.faves_coop.Favorite('urn:xanga:actions:homepage');
  187.   xgHomepage.name = 'Xanga.com';
  188.   xgHomepage.URL = 'http://www.xanga.com';
  189.  
  190.   this.xgService.children.addOnce(xgHomepage);
  191.   this.urn = this.xgService.id();
  192.  
  193.   this.webDetective = this.acUtils.useWebDetective("xanga.xml");
  194.  
  195.   this._profiler.profileEventEnd(evtID, "");
  196. }
  197.  
  198.  
  199. flockXGService.prototype.refresh =
  200. function flockXGService_refresh(aURN, aListener)
  201. {
  202.     debug("flockXGService refresh with aURN of "+aURN+"\n");
  203.  
  204.     // Introspection against what we're syncing - Identity or Account or Item?
  205.     var refreshItem = this.faves_coop.get(aURN);
  206.  
  207.   if (refreshItem instanceof this.faves_coop.Account) {
  208.     }
  209.   else if (refreshItem instanceof this.faves_coop.Favorite) {
  210.     }
  211.   else {
  212.         throw Components.results.NS_ERROR_ABORT;
  213.     }
  214. }
  215.  
  216. flockXGService.prototype.refreshAccount =
  217. function flockXGService_refreshAccount(aURN, aListener)
  218. {
  219.   debug("XGService - refreshAccount with aURN of "+aURN);
  220. }
  221.  
  222.  
  223. // BEGIN flockIBlogWebService interface
  224.  
  225. flockXGService.prototype.newPost = function(aListener, aBlogId, aPost, aPublish, aNotifications) {
  226.   dump("==== newPost in Xanga\n");
  227. /*  var authenticated = false;
  228.   var enum = this.faves_coop.accounts_root.children.enumerate();
  229.   while (enum.hasMoreElements()) {
  230.     var account = enum.getNext();
  231.     if (!account) continue; // getNext() can return NULL when hasMoreElements() is TRUE.
  232.     if ((account.serviceId == XANGA_CONTRACTID) && (account.isAuthenticated))
  233.       authenticated = true;
  234.   }
  235.  
  236.   if (!authenticated) {
  237.     var error = Components.classes['@flock.com/error;1']
  238.                           .createInstance(Components.interfaces.flockIError);
  239.     error.errorCode = error.BLOG_LOGIN_REQUIRED;
  240.     aListener.onError(error);
  241.     return;
  242.   }*/
  243.  
  244.   var notifsArray = new Array();
  245.   // var html = aPost.description + addTechnoratiTags(aPost.tags);
  246.   while (aNotifications.hasMore())
  247.     notifsArray.push(aNotifications.getNext());
  248.   //var comments = aPost.extra.getNext();
  249.   //var privacy = aPost.extra.getNext();
  250.   //var mood = aPost.extra.getNext().split('||');
  251.  
  252.   var textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"].getService(Components.interfaces.nsITextToSubURI);
  253.   var tags = "";
  254.   while (aPost.tags.hasMore())
  255.     tags += (aPost.tags.getNext() + '%2C');
  256.   var privacy = aPost.extra.getNext();
  257.   var comments = aPost.extra.getNext();
  258.  
  259.   function postForReal(aToken) {
  260.     var postMessage = '__EVENTTARGET='+
  261.                       '&__EVENTARGUMENT='+
  262.                       '&__VIEWSTATE=' + aToken +
  263.                       '&txtTitle=' + textToSubURI.ConvertAndEscape("UTF-8", aPost.title) +
  264.                       '&spellcheckbtn=false' +
  265.                       '&RadEContentTextareawerichtext=' +
  266.                       '&werichtext=++++++++++++++++++++++++++++++++++++++++++++++++' +
  267.                       '&tnames=' +
  268.                       '&ptag=tagname' +
  269.                       '&proftitle0=' +
  270.                       '&proftitle1=' +
  271.                       '&proftitle3=' +
  272.                       '&xztitle1=' +
  273.                       '&xztitle2=' +
  274.                       '&xzasin1=' +
  275.                       '&xzformat=' +
  276.                       '&xzextravalue=' +
  277.                       '&weprivacy=' + privacy
  278.                       '&txtRating=';
  279.     if (comments == "on")
  280.       postMessage += '&chkComments=on';
  281.     postMessage += '&btnSave=Save+Changes' +
  282.                       '&epropcurrstate=0' +
  283.                       '&commentcnt=0' +
  284.                       '&weuniqueid=0' +
  285.                       '&webgcolor=' +
  286.                       '&webdcolor=' +
  287.                       '&tprefid=29385413' +
  288.                       '&tpref2=' +
  289.                       '&tpref3=' +
  290.                       '&tpref4=' +
  291.                       '&tpref5=' +
  292.                       '&cncel=' +
  293.                       '&postvalues=' +
  294.                       '&photovalues=' +
  295.                       '&videovalues=' +
  296.                       '&audiovalues=' +
  297.                       '&bodyvalue=' + textToSubURI.ConvertAndEscape("UTF-8", aPost.description.replace(/\n/g, "<br/>")) +
  298.                       '&mediaargs=' +
  299.                       '&tagsoriginal=' +
  300.                       '&tagstodelete=%2C' +
  301.                       '&tagstoadd=%2C' + tags;
  302.  
  303.     var xhr2 = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance (Ci.nsIXMLHttpRequest);
  304.     xhr2.open ('POST', 'http://www.xanga.com/private/editorx.aspx', true);
  305.     xhr2.setRequestHeader ('Content-Type', 'application/x-www-form-urlencoded');
  306.     xhr2.setRequestHeader ('Content-Length', postMessage.length );
  307.     xhr2.setRequestHeader ('Referer', 'http://www.xanga.com/private/editorx.aspx');
  308.  
  309.     xhr2.onreadystatechange = function (aEvent) {
  310.       debug("readyState: "+xhr2.readyState);
  311.       if (xhr2.readyState == 4) {
  312.         debug("status: "+xhr2.status);
  313.         if ((xhr2.status != 200) && (xhr2.status != 302)) {
  314.           aListener.onError (xhr2.statusText);
  315.           return;
  316.         }
  317.         debug(xhr2.responseText);
  318.         aListener.onResult("");
  319.       }
  320.     }
  321.  
  322.     dump(" *** Post FOR REAL!!...\n");
  323.  
  324.     //dump(postMessage);
  325.     xhr2.send(postMessage);
  326.   }
  327.  
  328.   function getViewState() {
  329.     // Show the editor to get the "viewState" token
  330.     var xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
  331.     xhr.open('GET', 'http://www.xanga.com/private/editorx.aspx', true);
  332.     xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  333.  
  334.     xhr.onreadystatechange = function (aEvent) {
  335.       if (xhr.readyState == 4) {
  336.         if (xhr.status != 200) {
  337.           aListener.onError (xhr.statusText);
  338.           return;
  339.         }
  340.         //dump(xhr.responseText);
  341.  
  342.         if (xhr.responseText.match("PLEASE SIGN IN")) {
  343.           var error = Components.classes['@flock.com/error;1']
  344.                           .createInstance(Ci.flockIError);
  345.           error.errorCode = error.BLOG_LOGIN_REQUIRED;
  346.           aListener.onError(error);
  347.           return;
  348.         }
  349.         // Get the token and post for real
  350.         var theHash = xhr.responseText.match(/(?:id\=\"\__VIEWSTATE\"\svalue\=\")(.+)(?=\")/);
  351.         debug("theHash: "+theHash+"\n");
  352.         debug("theHash[1]: "+theHash[1]+"\n");
  353.  
  354.         if (theHash != null){
  355.           var token = theHash[1];
  356.           debug("*****\n*****\n TOKEN: "+token+"\n");
  357.           postForReal(token);
  358.         }
  359.       }
  360.     }
  361.     xhr.send(null);
  362.   }
  363.  
  364.   getViewState();
  365. }
  366.  
  367. flockXGService.prototype.editPost = function(aListener, aBlogId, aPost, aPublish, atomid, editURI, aNotifications){
  368. }
  369.  
  370. flockXGService.prototype.deletePost = function(aListener, aBlogId, aPostid){
  371. }
  372.  
  373. flockXGService.prototype.getUsersBlogs = function(aListener, aAccount){
  374. }
  375.  
  376. flockXGService.prototype.getRecentPosts = function(aListener, aBlogId, aNumber){
  377. }
  378.  
  379. flockXGService.prototype.getCategoryList = function(aListener, aBlogId){
  380. }
  381. // END flockIBlogWebService interface
  382.  
  383.  
  384. // BEGIN flockIManageableWebService interface
  385. flockXGService.prototype.getAccountIDFromDocument =
  386. function flockXGService_getAccountIDFromDocument(aDocument)
  387. {
  388.   this.logger.debug("{flockIManageableWebService}.getAccountIDFromDocument(aDocument)");
  389.   aDocument.QueryInterface(Ci.nsIDOMHTMLDocument);
  390.  
  391.   var results = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
  392.   dump("Let's find what Xanga user it is\n");
  393.   if (this.webDetective.detect("xanga", "accountinfo", aDocument, results)) {
  394.     var accountID = results.getPropertyAsAString("accountid");
  395.     dump(accountID+" it is!\n");
  396.     if (accountID && accountID.length) {
  397.       return accountID;
  398.     }
  399.   }
  400.   else {
  401.     dump("I don't know :(\n");
  402.   }
  403.  
  404.   return null;
  405.  
  406. /*  var title = aDocument.title;
  407.   debug(title);
  408.   if (title.match(/(.+)\'s\sXanga\sSite/)) {
  409.     var val = RegExp.$1;
  410.     this.logger.debug(" - found account ID: "+val);
  411.     return val;
  412.   } else
  413.     debug("Xanga: unable to find the username from the page.\n");
  414.  
  415.   return null;*/
  416. }
  417.  
  418. flockXGService.prototype.updateAccountStatusFromDocument =
  419. function flockXGService_updateAccountStatusFromDocument(aDocument)
  420. {
  421.   this.logger.debug("{flockIManageableWebService}.updateAccountStatusFromDocument(aDocument)");
  422.   if (this.webDetective.detect("xanga", "loggedin", aDocument, null)) {
  423.     debug("WOOT WOOT Xanga user logged IN!\n");
  424.     var accountID = this.getAccountIDFromDocument(aDocument);
  425.     var acctURN = this.acUtils.getAccountURNById(this.urn, accountID);
  426.  
  427.       var avatarURL;
  428.       var results = Cc["@mozilla.org/hash-property-bag;1"].createInstance(Ci.nsIWritablePropertyBag2);
  429.  
  430.       if(this.webDetective.detect("xanga", "avatarURLDetect", aDocument, results)) {
  431.         try {
  432.           avatarURL = results.getPropertyAsAString("avatarURL");
  433.         } catch(e) {
  434.           // No avatar found
  435.         }
  436.       }
  437.  
  438.       var acctURN = this.acUtils.getAccountURNById(this.urn, accountID);
  439.       var acct = this.faves_coop.get(acctURN);
  440.       acct.avatar = avatarURL;
  441.  
  442.     var accounts = this.faves_coop.Account.find({serviceId: XANGA_CONTRACTID});
  443.     for (var i = 0; i < accounts.length; i++) {
  444.       if (accounts[i].id() == acctURN) {
  445.         accounts[i].isAuthenticated = true;
  446.       } else {
  447.         accounts[i].isAuthenticated = false;
  448.       }
  449.     }
  450.   } else if (this.webDetective.detect("xanga", "loggedout", aDocument, null)) {
  451.     debug("WOOT WOOT Xanga user logged OUT!\n");
  452.     this.acUtils.markAllAccountsAsLoggedOut(XANGA_CONTRACTID);
  453.   }
  454. }
  455. // END flockIManageableWebService interface
  456.  
  457.  
  458.  
  459. // ================================================
  460. // ========== BEGIN XPCOM Module support ==========
  461. // ================================================
  462.  
  463. function createModule(aParams) {
  464.   return {
  465.     registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
  466.       var aCompMgr = aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
  467.       aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
  468.                                         aParams.contractID, aFileSpec,
  469.                                         aLocation, aType );
  470.       var catMgr = Cc["@mozilla.org/categorymanager;1"]
  471.         .getService(Ci.nsICategoryManager);
  472.       if (!aParams.categories) { aParams.categories = []; }
  473.       for (var i = 0; i < aParams.categories.length; i++) {
  474.         var cat = aParams.categories[i];
  475.         catMgr.addCategoryEntry( cat.category, cat.entry,
  476.                                  cat.value, true, true );
  477.       }
  478.     },
  479.     getClassObject: function (aCompMgr, aCID, aIID) {
  480.       if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
  481.       if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
  482.       return { // Factory
  483.         createInstance: function (aOuter, aIID) {
  484.           if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
  485.           var comp = new aParams.componentClass();
  486.           if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
  487.           return comp.QueryInterface(aIID);
  488.         }
  489.       };
  490.     },
  491.     canUnload: function (aCompMgr) { return true; }
  492.   };
  493. }
  494.  
  495. // NS Module entrypoint
  496. function NSGetModule(aCompMgr, aFileSpec) {
  497.   return createModule({
  498.     componentClass: flockXGService,
  499.     CID: XANGA_CID,
  500.     contractID: XANGA_CONTRACTID,
  501.     componentName: CATEGORY_COMPONENT_NAME,
  502.     implementationFunc: function (aComp) { getCompTK().addAllInterfaces(aComp); },
  503.     categories: [
  504.       { category: "wsm-startup", entry: CATEGORY_COMPONENT_NAME, value: XANGA_CONTRACTID },
  505.       { category: "flockWebService", entry: CATEGORY_ENTRY_NAME, value: XANGA_CONTRACTID }
  506.     ]
  507.   });
  508. }
  509.  
  510. // ========== END XPCOM Module support ==========
  511.  
  512.  
  513.  
  514. // ================================================
  515. // ========== BEGIN flockXGAccount class ==========
  516. // ================================================
  517.  
  518.  
  519. function flockXGAccount()
  520. {
  521.   this.logger = Cc["@flock.com/logger;1"].createInstance(Ci.flockILogger);
  522.   this.logger.init("xangaAccount");
  523.   this.faves_coop = Cc["@flock.com/singleton;1"]
  524.                     .getService(Ci.flockISingleton)
  525.                     .getSingleton("chrome://flock/content/common/load-faves-coop.js")
  526.                     .wrappedJSObject;
  527.   this.acUtils = Cc["@flock.com/account-utils;1"].getService(Ci.flockIAccountUtils);
  528.   this._ctk = {
  529.     interfaces: [
  530.       "nsISupports",
  531.       "flockIWebServiceAccount",
  532.       "flockIBlogWebServiceAccount"
  533.     ]
  534.   };
  535.   getCompTK().addAllInterfaces(this);
  536. }
  537.  
  538.  
  539. // BEGIN flockIWebServiceAccount
  540. flockXGAccount.prototype.activate = function(aListener) {
  541. }
  542. flockXGAccount.prototype.deactivate = function(aListener) {
  543. }
  544. // END flockIWebServiceAccount
  545.  
  546.  
  547. // flockIBlogWebServiceAccount implementation
  548. flockXGAccount.prototype.getBlogs = function() {
  549.   this.logger.info("{flockIBlogWebServiceAccount}.getBlogs()");
  550.   var blogsEnum = {
  551.     QueryInterface : function(iid) {
  552.       if (!iid.equals(Ci.nsISupports) &&
  553.           !iid.equals(Ci.nsISimpleEnumerator))
  554.       {
  555.         throw Components.results.NS_ERROR_NO_INTERFACE;
  556.       }
  557.       return this;
  558.     },
  559.     hasMoreElements : function() {
  560.       return false;
  561.     },
  562.     getNext : function() {
  563.     }
  564.   };
  565.   return blogsEnum;
  566. }
  567.